package cc.shacocloud.mirage.restful.bind.converter.json;

import cc.shacocloud.mirage.utils.ClassUtil;
import cc.shacocloud.mirage.utils.KotlinDetector;
import cc.shacocloud.mirage.utils.map.LinkedMultiValueMap;
import cc.shacocloud.mirage.utils.map.MultiValueMap;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair;
import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
import com.fasterxml.jackson.dataformat.smile.SmileFactory;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;

/**
 * 用于使用连贯API创建{@link ObjectMapper}实例的构建器。
 *
 * <p>
 * 它定制Jackson的默认属性如下:
 * <ul>
 *   <li>{@link MapperFeature#DEFAULT_VIEW_INCLUSION} 是禁用的</li>
 *   <li>{@link DeserializationFeature#FAIL_ON_UNKNOWN_PROPERTIES} 是禁用的</li>
 * </ul>
 *
 * <p>
 * 如果在类路径中被检测到，它还会自动注册以下众所周知的模块:
 * <ul>
 *    <li>
 *       <a href="https://github.com/FasterXML/jackson-datatype-jdk8">jackson-datatype-jdk8</a>:
 * 对其他Java 8类型的支持，如 {@link java.util.Optional}
 *   </li>
 *   <li>
 *       <a href="https://github.com/FasterXML/jackson-datatype-jsr310">jackson-datatype-jsr310</a>:
 * 支持Java 8日期和时间API类型
 *   </li>
 *   <li>
 *       <a href="https://github.com/FasterXML/jackson-datatype-joda">jackson-datatype-joda</a>:
 * 支持Joda-Time类型
 *   </li>
 *   <li>
 *       <a href="https://github.com/FasterXML/jackson-module-kotlin">jackson-module-kotlin</a>:
 * 支持Kotlin类和数据类
 *    </li>
 * </ul>
 *
 * @see #build()
 * @see #configure(ObjectMapper)
 */
@Slf4j
public class Jackson2ObjectMapperBuilder {
    
    private static volatile boolean kotlinWarningLogged = false;
    
    private final Map<Class<?>, Class<?>> mixIns = new LinkedHashMap<>();
    
    private final Map<Class<?>, JsonSerializer<?>> serializers = new LinkedHashMap<>();
    
    private final Map<Class<?>, JsonDeserializer<?>> deserializers = new LinkedHashMap<>();
    
    private final Map<PropertyAccessor, JsonAutoDetect.Visibility> visibilities = new LinkedHashMap<>();
    
    private final Map<Object, Boolean> features = new LinkedHashMap<>();
    
    @Nullable
    private JsonFactory factory;
    
    @Nullable
    private DateFormat dateFormat;
    
    @Nullable
    private Locale locale;
    
    @Nullable
    private TimeZone timeZone;
    
    @Nullable
    private AnnotationIntrospector annotationIntrospector;
    
    @Nullable
    private PropertyNamingStrategy propertyNamingStrategy;
    
    @Nullable
    private TypeResolverBuilder<?> defaultTyping;
    
    @Nullable
    private JsonInclude.Include serializationInclusion;
    
    @Nullable
    private FilterProvider filters;
    
    @Nullable
    private List<Module> modules;
    
    @Nullable
    private Class<? extends Module>[] moduleClasses;
    
    private boolean findModulesViaServiceLoader = false;
    
    private boolean findWellKnownModules = true;
    
    private ClassLoader moduleClassLoader = getClass().getClassLoader();
    
    @Nullable
    private HandlerInstantiator handlerInstantiator;
    
    /**
     * 获取一个{@link Jackson2ObjectMapperBuilder}实例，以便构建一个普通的JSON {@link ObjectMapper}实例。
     */
    @Contract(" -> new")
    public static @NotNull Jackson2ObjectMapperBuilder json() {
        return new Jackson2ObjectMapperBuilder();
    }
    
    /**
     * 获取一个{@link Jackson2ObjectMapperBuilder}实例，以构建一个Smile数据格式{@link ObjectMapper}实例。
     */
    public static Jackson2ObjectMapperBuilder smile() {
        return new Jackson2ObjectMapperBuilder().factory(new SmileFactoryInitializer().create());
    }
    
    /**
     * 获取一个{@link Jackson2ObjectMapperBuilder}实例，以便构建一个CBOR数据格式{@link ObjectMapper}实例。
     */
    public static Jackson2ObjectMapperBuilder cbor() {
        return new Jackson2ObjectMapperBuilder().factory(new CborFactoryInitializer().create());
    }
    
    /**
     * 定义用于创建{@link ObjectMapper} 实例的{@link JsonFactory}。
     */
    public Jackson2ObjectMapperBuilder factory(JsonFactory factory) {
        this.factory = factory;
        return this;
    }
    
    /**
     * 使用给定的{@link DateFormat}定义日期/时间的格式
     * <p>
     * 注意:根据Jackson的线程安全规则，设置这个属性将使暴露的{@link ObjectMapper} 是非线程安全的。
     *
     * @see #simpleDateFormat(String)
     */
    public Jackson2ObjectMapperBuilder dateFormat(DateFormat dateFormat) {
        this.dateFormat = dateFormat;
        return this;
    }
    
    /**
     * 使用{@link SimpleDateFormat}定义日期/时间格式。
     * <p>
     * 注意:根据Jackson的线程安全规则，设置这个属性将使暴露的{@link ObjectMapper} 是非线程安全的。
     *
     * @see #dateFormat(DateFormat)
     */
    public Jackson2ObjectMapperBuilder simpleDateFormat(String format) {
        this.dateFormat = new SimpleDateFormat(format);
        return this;
    }
    
    /**
     * 重写用于格式化的默认{@link Locale}。
     * 使用的默认值是{@link Locale#getDefault()}。
     */
    public Jackson2ObjectMapperBuilder locale(Locale locale) {
        this.locale = locale;
        return this;
    }
    
    /**
     * 重写用于格式化的默认{@link Locale}。
     * 使用的默认值是{@link Locale#getDefault()}。
     *
     * @param localeString 区域设置ID作为字符串表示
     */
    public Jackson2ObjectMapperBuilder locale(String localeString) {
        this.locale = Locale.forLanguageTag(localeString);
        return this;
    }
    
    /**
     * 重写用于格式化的默认{@link TimeZone}。
     * 默认值是UTC(不是本地时区)。
     */
    public Jackson2ObjectMapperBuilder timeZone(TimeZone timeZone) {
        this.timeZone = timeZone;
        return this;
    }
    
    /**
     * 重写用于格式化的默认{@link TimeZone}。
     * 默认值是UTC(不是本地时区)。
     *
     * @param timeZoneString 区域ID作为字符串表示
     */
    public Jackson2ObjectMapperBuilder timeZone(String timeZoneString) {
        this.timeZone = TimeZone.getTimeZone(timeZoneString);
        return this;
    }
    
    /**
     * 为序列化和反序列化设置{@link AnnotationIntrospector}。
     */
    public Jackson2ObjectMapperBuilder annotationIntrospector(AnnotationIntrospector annotationIntrospector) {
        this.annotationIntrospector = annotationIntrospector;
        return this;
    }
    
    /**
     * 可选的{@link #annotationIntrospector} ,该方法允许与当前设置的内省器(例如via)组合而不是替换
     * {@link AnnotationIntrospectorPair#pair(AnnotationIntrospector, AnnotationIntrospector)}.
     *
     * @param pairingFunction 要应用于当前设置的内省器(可能是{@code null})的函数;函数的结果变成新的自省器。
     */
    public Jackson2ObjectMapperBuilder annotationIntrospector(
            Function<AnnotationIntrospector, AnnotationIntrospector> pairingFunction) {
        
        this.annotationIntrospector = pairingFunction.apply(this.annotationIntrospector);
        return this;
    }
    
    /**
     * 指定{@link com.fasterxml.jackson.databind。配置{@link ObjectMapper}。
     */
    public Jackson2ObjectMapperBuilder propertyNamingStrategy(PropertyNamingStrategy propertyNamingStrategy) {
        this.propertyNamingStrategy = propertyNamingStrategy;
        return this;
    }
    
    /**
     * 指定一个{@link TypeResolverBuilder}用于Jackson的默认输入。
     */
    public Jackson2ObjectMapperBuilder defaultTyping(TypeResolverBuilder<?> typeResolverBuilder) {
        this.defaultTyping = typeResolverBuilder;
        return this;
    }
    
    /**
     * 为序列化设置自定义包含策略。
     *
     * @see com.fasterxml.jackson.annotation.JsonInclude.Include
     */
    public Jackson2ObjectMapperBuilder serializationInclusion(JsonInclude.Include serializationInclusion) {
        this.serializationInclusion = serializationInclusion;
        return this;
    }
    
    /**
     * 设置要使用的全局过滤器，以支持{@link JsonFilter @JsonFilter}注解的POJO。
     *
     * @see MappingJacksonValue#setFilters(FilterProvider)
     */
    public Jackson2ObjectMapperBuilder filters(FilterProvider filters) {
        this.filters = filters;
        return this;
    }
    
    /**
     * 添加混合注解以用于扩充指定的类或接口。
     *
     * @param target      要有效覆盖其注解的类(或接口)
     * @param mixinSource 类(或接口)，其注解将作为值“添加”到目标的注解中
     * @see com.fasterxml.jackson.databind.ObjectMapper#addMixIn(Class, Class)
     */
    public Jackson2ObjectMapperBuilder mixIn(Class<?> target, Class<?> mixinSource) {
        this.mixIns.put(target, mixinSource);
        return this;
    }
    
    /**
     * 添加混合注解以用于扩充指定的类或接口。
     *
     * @param mixIns 一个带有目标类(或接口)的条目的映射，
     *               目标类(或接口)的注解要有效地作为键覆盖，
     *               而混合类(或接口)的注解要作为值“添加”到目标的注解。
     * @see com.fasterxml.jackson.databind.ObjectMapper#addMixIn(Class, Class)
     */
    public Jackson2ObjectMapperBuilder mixIns(Map<Class<?>, Class<?>> mixIns) {
        this.mixIns.putAll(mixIns);
        return this;
    }
    
    /**
     * 配置自定义序列化器。每个序列化器都为{@link JsonSerializer#handledType()}返回的类型注册，该类型不能是{@code null}。
     *
     * @see #serializersByType(Map)
     */
    public Jackson2ObjectMapperBuilder serializers(JsonSerializer<?>... serializers) {
        for (JsonSerializer<?> serializer : serializers) {
            Class<?> handledType = serializer.handledType();
            if (handledType == null || handledType == Object.class) {
                throw new IllegalArgumentException("Unknown handled type in " + serializer.getClass().getName());
            }
            this.serializers.put(serializer.handledType(), serializer);
        }
        return this;
    }
    
    /**
     * 为给定类型配置自定义序列化器。
     *
     * @see #serializers(JsonSerializer...)
     */
    public Jackson2ObjectMapperBuilder serializerByType(Class<?> type, JsonSerializer<?> serializer) {
        this.serializers.put(type, serializer);
        return this;
    }
    
    /**
     * 为给定类型配置自定义序列化器。
     *
     * @see #serializers(JsonSerializer...)
     */
    public Jackson2ObjectMapperBuilder serializersByType(Map<Class<?>, JsonSerializer<?>> serializers) {
        this.serializers.putAll(serializers);
        return this;
    }
    
    /**
     * 配置自定义反序列化器。每个反序列化器都为{@link JsonDeserializer#handledType()}返回的类型注册，该类型不能是{@code null}。
     *
     * @see #deserializersByType(Map)
     */
    public Jackson2ObjectMapperBuilder deserializers(JsonDeserializer<?>... deserializers) {
        for (JsonDeserializer<?> deserializer : deserializers) {
            Class<?> handledType = deserializer.handledType();
            if (handledType == null || handledType == Object.class) {
                throw new IllegalArgumentException("Unknown handled type in " + deserializer.getClass().getName());
            }
            this.deserializers.put(deserializer.handledType(), deserializer);
        }
        return this;
    }
    
    /**
     * 为给定类型配置自定义反序列化器。
     */
    public Jackson2ObjectMapperBuilder deserializerByType(Class<?> type, JsonDeserializer<?> deserializer) {
        this.deserializers.put(type, deserializer);
        return this;
    }
    
    /**
     * 为给定类型配置自定义反序列化器。
     */
    public Jackson2ObjectMapperBuilder deserializersByType(Map<Class<?>, JsonDeserializer<?>> deserializers) {
        this.deserializers.putAll(deserializers);
        return this;
    }
    
    /**
     * {@link MapperFeature#AUTO_DETECT_FIELDS}选项的快捷方式。
     */
    public Jackson2ObjectMapperBuilder autoDetectFields(boolean autoDetectFields) {
        this.features.put(MapperFeature.AUTO_DETECT_FIELDS, autoDetectFields);
        return this;
    }
    
    /**
     * {@link MapperFeature#AUTO_DETECT_SETTERS}
     * {@link MapperFeature#AUTO_DETECT_GETTERS}
     * {@link MapperFeature#AUTO_DETECT_IS_GETTERS}
     */
    public Jackson2ObjectMapperBuilder autoDetectGettersSetters(boolean autoDetectGettersSetters) {
        this.features.put(MapperFeature.AUTO_DETECT_GETTERS, autoDetectGettersSetters);
        this.features.put(MapperFeature.AUTO_DETECT_SETTERS, autoDetectGettersSetters);
        this.features.put(MapperFeature.AUTO_DETECT_IS_GETTERS, autoDetectGettersSetters);
        return this;
    }
    
    /**
     * {@link MapperFeature#DEFAULT_VIEW_INCLUSION}选项的快捷方式。
     */
    public Jackson2ObjectMapperBuilder defaultViewInclusion(boolean defaultViewInclusion) {
        this.features.put(MapperFeature.DEFAULT_VIEW_INCLUSION, defaultViewInclusion);
        return this;
    }
    
    /**
     * {@link DeserializationFeature#FAIL_ON_UNKNOWN_PROPERTIES}选项的快捷方式。
     */
    public Jackson2ObjectMapperBuilder failOnUnknownProperties(boolean failOnUnknownProperties) {
        this.features.put(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, failOnUnknownProperties);
        return this;
    }
    
    /**
     * {@link SerializationFeature#FAIL_ON_EMPTY_BEANS}选项的快捷方式。
     */
    public Jackson2ObjectMapperBuilder failOnEmptyBeans(boolean failOnEmptyBeans) {
        this.features.put(SerializationFeature.FAIL_ON_EMPTY_BEANS, failOnEmptyBeans);
        return this;
    }
    
    /**
     * {@link SerializationFeature#INDENT_OUTPUT}选项的快捷方式。
     */
    public Jackson2ObjectMapperBuilder indentOutput(boolean indentOutput) {
        this.features.put(SerializationFeature.INDENT_OUTPUT, indentOutput);
        return this;
    }
    
    /**
     * 指定可见性以限制自动检测的属性类型。
     *
     * @see com.fasterxml.jackson.annotation.PropertyAccessor
     * @see com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility
     */
    public Jackson2ObjectMapperBuilder visibility(PropertyAccessor accessor, JsonAutoDetect.Visibility visibility) {
        this.visibilities.put(accessor, visibility);
        return this;
    }
    
    /**
     * 指定要启用的特性。
     *
     * @see com.fasterxml.jackson.core.JsonParser.Feature
     * @see com.fasterxml.jackson.core.JsonGenerator.Feature
     * @see com.fasterxml.jackson.databind.SerializationFeature
     * @see com.fasterxml.jackson.databind.DeserializationFeature
     * @see com.fasterxml.jackson.databind.MapperFeature
     */
    public Jackson2ObjectMapperBuilder featuresToEnable(Object @NotNull ... featuresToEnable) {
        for (Object feature : featuresToEnable) {
            this.features.put(feature, Boolean.TRUE);
        }
        return this;
    }
    
    /**
     * 指定要禁用的特性。
     *
     * @see com.fasterxml.jackson.core.JsonParser.Feature
     * @see com.fasterxml.jackson.core.JsonGenerator.Feature
     * @see com.fasterxml.jackson.databind.SerializationFeature
     * @see com.fasterxml.jackson.databind.DeserializationFeature
     * @see com.fasterxml.jackson.databind.MapperFeature
     */
    public Jackson2ObjectMapperBuilder featuresToDisable(Object @NotNull ... featuresToDisable) {
        for (Object feature : featuresToDisable) {
            this.features.put(feature, Boolean.FALSE);
        }
        return this;
    }
    
    /**
     * 指定要向{@link ObjectMapper}注册的一个或多个模块。多个调用不是附加的，最后一个定义要*注册的模块。
     * 注意:如果设置了此选项，将不会发现模块——不是通过 Jackson找到的，
     * 因此，在这里指定一个空列表将禁止任何类型的模块检测。
     * <p>
     * 指定this或{@link #modulesToInstall}，不要同时指定两者。
     *
     * @see #modules(List)
     * @see com.fasterxml.jackson.databind.Module
     */
    public Jackson2ObjectMapperBuilder modules(Module... modules) {
        return modules(Arrays.asList(modules));
    }
    
    /**
     * @see #modules(Module...)
     * @see com.fasterxml.jackson.databind.Module
     */
    public Jackson2ObjectMapperBuilder modules(List<Module> modules) {
        this.modules = new LinkedList<>(modules);
        this.findModulesViaServiceLoader = false;
        this.findWellKnownModules = false;
        return this;
    }
    
    /**
     * 指定要向{@link ObjectMapper}注册的一个或多个模块。
     * 多个调用不是附加的，最后一个调用定义了要注册的模块。
     * <p>
     * 指定this或{@link #modules}，不要同时指定两者。
     *
     * @see com.fasterxml.jackson.databind.Module
     */
    public Jackson2ObjectMapperBuilder modulesToInstall(Module... modules) {
        this.modules = Arrays.asList(modules);
        this.findWellKnownModules = true;
        return this;
    }
    
    /**
     * @see #modulesToInstall(Module...)
     * @see com.fasterxml.jackson.databind.Module
     */
    @SuppressWarnings("unchecked")
    public Jackson2ObjectMapperBuilder modulesToInstall(Class<? extends Module>... modules) {
        this.moduleClasses = modules;
        this.findWellKnownModules = true;
        return this;
    }
    
    /**
     * 根据类路径中的META-INF元数据，设置是否让Jackson通过JDK ServiceLoader查找可用模块。
     *
     * @see com.fasterxml.jackson.databind.ObjectMapper#findModules()
     */
    public Jackson2ObjectMapperBuilder findModulesViaServiceLoader(boolean findModules) {
        this.findModulesViaServiceLoader = findModules;
        return this;
    }
    
    /**
     * 设置用于加载Jackson扩展模块的类加载器。
     */
    public Jackson2ObjectMapperBuilder moduleClassLoader(ClassLoader moduleClassLoader) {
        this.moduleClassLoader = moduleClassLoader;
        return this;
    }
    
    /**
     * 定制Jackson处理程序的构造({@link JsonSerializer}、{@link JsonDeserializer}、{@link KeyDeserializer}、
     * {@code TypeResolverBuilder}和{@code TypeIdResolver})。
     */
    public Jackson2ObjectMapperBuilder handlerInstantiator(HandlerInstantiator handlerInstantiator) {
        this.handlerInstantiator = handlerInstantiator;
        return this;
    }
    
    /**
     * 构建一个新的{@link ObjectMapper}实例。
     * <p>
     * 每个构建操作都会生成一个独立的{@link ObjectMapper}实例。
     * 构建器的设置可以被修改，通过随后的构建操作然后根据最近的设置生成一个新的{@link ObjectMapper}。
     *
     * @return 新构建的ObjectMapper
     */
    @SuppressWarnings("unchecked")
    public <T extends ObjectMapper> T build() {
        ObjectMapper mapper;
        mapper = (this.factory != null ? new ObjectMapper(this.factory) : new ObjectMapper());
        configure(mapper);
        return (T) mapper;
    }
    
    /**
     * 使用此构建器的设置配置现有的{@link ObjectMapper}实例。这可以应用于任意数量的{@code ObjectMappers}。
     *
     * @param objectMapper 要配置的ObjectMapper
     */
    public void configure(@NotNull ObjectMapper objectMapper) {
        
        MultiValueMap<Object, Module> modulesToRegister = new LinkedMultiValueMap<>();
        if (this.findModulesViaServiceLoader) {
            ObjectMapper.findModules(this.moduleClassLoader).forEach(module -> registerModule(module, modulesToRegister));
        } else if (this.findWellKnownModules) {
            registerWellKnownModulesIfAvailable(modulesToRegister);
        }
        
        if (this.modules != null) {
            this.modules.forEach(module -> registerModule(module, modulesToRegister));
        }
        if (this.moduleClasses != null) {
            for (Class<? extends Module> moduleClass : this.moduleClasses) {
                if (Objects.nonNull(moduleClass)) {
                    registerModule(ClassUtil.instantiateClass(moduleClass), modulesToRegister);
                }
            }
        }
        List<Module> modules = new ArrayList<>();
        for (List<Module> nestedModules : modulesToRegister.values()) {
            modules.addAll(nestedModules);
        }
        objectMapper.registerModules(modules);
        
        if (this.dateFormat != null) {
            objectMapper.setDateFormat(this.dateFormat);
        }
        if (this.locale != null) {
            objectMapper.setLocale(this.locale);
        }
        if (this.timeZone != null) {
            objectMapper.setTimeZone(this.timeZone);
        }
        
        if (this.annotationIntrospector != null) {
            objectMapper.setAnnotationIntrospector(this.annotationIntrospector);
        }
        if (this.propertyNamingStrategy != null) {
            objectMapper.setPropertyNamingStrategy(this.propertyNamingStrategy);
        }
        if (this.defaultTyping != null) {
            objectMapper.setDefaultTyping(this.defaultTyping);
        }
        if (this.serializationInclusion != null) {
            objectMapper.setSerializationInclusion(this.serializationInclusion);
        }
        
        if (this.filters != null) {
            objectMapper.setFilterProvider(this.filters);
        }
        
        this.mixIns.forEach(objectMapper::addMixIn);
        
        if (!this.serializers.isEmpty() || !this.deserializers.isEmpty()) {
            SimpleModule module = new SimpleModule();
            addSerializers(module);
            addDeserializers(module);
            objectMapper.registerModule(module);
        }
        
        this.visibilities.forEach(objectMapper::setVisibility);
        
        customizeDefaultFeatures(objectMapper);
        this.features.forEach((feature, enabled) -> configureFeature(objectMapper, feature, enabled));
        
        if (this.handlerInstantiator != null) {
            objectMapper.setHandlerInstantiator(this.handlerInstantiator);
        }
    }
    
    private void registerModule(Module module, MultiValueMap<Object, Module> modulesToRegister) {
        if (module.getTypeId() == null) {
            modulesToRegister.add(SimpleModule.class.getName(), module);
        } else {
            modulesToRegister.set(module.getTypeId(), module);
        }
    }
    
    private void customizeDefaultFeatures(ObjectMapper objectMapper) {
        if (!this.features.containsKey(MapperFeature.DEFAULT_VIEW_INCLUSION)) {
            configureFeature(objectMapper, MapperFeature.DEFAULT_VIEW_INCLUSION, false);
        }
        if (!this.features.containsKey(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
            configureFeature(objectMapper, DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        }
    }
    
    @SuppressWarnings("unchecked")
    private <T> void addSerializers(SimpleModule module) {
        this.serializers.forEach((type, serializer) ->
                module.addSerializer((Class<? extends T>) type, (JsonSerializer<T>) serializer));
    }
    
    
    // 便利工厂方法
    
    @SuppressWarnings("unchecked")
    private <T> void addDeserializers(SimpleModule module) {
        this.deserializers.forEach((type, deserializer) ->
                module.addDeserializer((Class<T>) type, (JsonDeserializer<? extends T>) deserializer));
    }
    
    private void configureFeature(ObjectMapper objectMapper, Object feature, boolean enabled) {
        if (feature instanceof JsonParser.Feature) {
            objectMapper.configure((JsonParser.Feature) feature, enabled);
        } else if (feature instanceof JsonGenerator.Feature) {
            objectMapper.configure((JsonGenerator.Feature) feature, enabled);
        } else if (feature instanceof SerializationFeature) {
            objectMapper.configure((SerializationFeature) feature, enabled);
        } else if (feature instanceof DeserializationFeature) {
            objectMapper.configure((DeserializationFeature) feature, enabled);
        } else if (feature instanceof MapperFeature) {
            objectMapper.configure((MapperFeature) feature, enabled);
        } else {
            throw new RuntimeException("未知功能类: " + feature.getClass().getName());
        }
    }
    
    @SuppressWarnings("unchecked")
    private void registerWellKnownModulesIfAvailable(@NotNull MultiValueMap<Object, Module> modulesToRegister) {
        try {
            Class<? extends Module> jdk8ModuleClass = (Class<? extends Module>)
                    ClassUtil.forName("com.fasterxml.jackson.datatype.jdk8.Jdk8Module", this.moduleClassLoader);
            Module jdk8Module = ClassUtil.instantiateClass(jdk8ModuleClass);
            modulesToRegister.set(jdk8Module.getTypeId(), jdk8Module);
        } catch (ClassNotFoundException ex) {
            // jackson-datatype-jdk8 不可用
        }
        
        try {
            Class<? extends Module> javaTimeModuleClass = (Class<? extends Module>)
                    ClassUtil.forName("com.fasterxml.jackson.datatype.jsr310.JavaTimeModule", this.moduleClassLoader);
            Module javaTimeModule = ClassUtil.instantiateClass(javaTimeModuleClass);
            modulesToRegister.set(javaTimeModule.getTypeId(), javaTimeModule);
        } catch (ClassNotFoundException ex) {
            // jackson-datatype-jsr310 不可用
        }
        
        // Joda-Time present?
        if (ClassUtil.isPresent("org.joda.time.LocalDate", this.moduleClassLoader)) {
            try {
                Class<? extends Module> jodaModuleClass = (Class<? extends Module>)
                        ClassUtil.forName("com.fasterxml.jackson.datatype.joda.JodaModule", this.moduleClassLoader);
                Module jodaModule = ClassUtil.instantiateClass(jodaModuleClass);
                modulesToRegister.set(jodaModule.getTypeId(), jodaModule);
            } catch (ClassNotFoundException ex) {
                // jackson-datatype-joda 不可用
            }
        }
        
        // Kotlin present?
        if (KotlinDetector.isKotlinPresent()) {
            try {
                Class<? extends Module> kotlinModuleClass = (Class<? extends Module>)
                        ClassUtil.forName("com.fasterxml.jackson.module.kotlin.KotlinModule", this.moduleClassLoader);
                Module kotlinModule = ClassUtil.instantiateClass(kotlinModuleClass);
                modulesToRegister.set(kotlinModule.getTypeId(), kotlinModule);
            } catch (ClassNotFoundException ex) {
                if (!kotlinWarningLogged) {
                    kotlinWarningLogged = true;
                    log.warn("对于Jackson Kotlin类支持，请添加 " +
                            "\"com.fasterxml.jackson.module:jackson-module-kotlin\" 到类路径");
                }
            }
        }
    }
    
    private static class SmileFactoryInitializer {
        
        @Contract(" -> new")
        public @NotNull JsonFactory create() {
            return new SmileFactory();
        }
    }
    
    
    private static class CborFactoryInitializer {
        
        @Contract(" -> new")
        public @NotNull JsonFactory create() {
            return new CBORFactory();
        }
    }
    
}
